<?php
require_once($common_data_server.'modules/shop/cart.php');
require_once($common_data_server.'modules/shop/order.php');

/********************************************************
Project: Базовый класс ЭМ
Author:  Холодий Андрей
Version: 1.0
Date:    12.01.2004 13:04
********************************************************/

 /**Базовый класс ЭМ
  * @author  Холодий Андрей
  * @version 1.1
  * @copyright Copyright 2003, РБК СОФТ
  * @abstract
  * @package E-shop
  */

class shop extends module {

 /**Путь к шаблону
  * @access public
  * @var string
  */
  var $path_tmpl;

 /**Шаблон
  * @access public
  * @var object
  */
  var $tmpl;

 /**Валюта в которой выводятся цены
  * @access public
  * @var array
  */
  var $publishedCurrency = array();

 /**Валюта по которой продаются товары
  * @access public
  * @var array
  */
  var $mainCurrency = array();

  /**Вариант использования "Форма аутентификации"
   * @return mixed
   */
  function modeAuth() {

  	if ($_GET['from_url']) $this -> q_param['from_url'] = $_GET['from_url'];

	$this -> tmpl -> setVar( "_goToPage", 'index.php');
	$this -> tmpl -> setVar( "_goToReminder", $this -> go_to_page($this -> view_param["goToReminder"]));
	$this -> tmpl -> setVar( "_goToRegistration", $this -> go_to_page($this -> view_param["goToRegistration"]));
	$this -> tmpl -> setVar( "from_url", htmlspecialchars( $this -> q_param['from_url'] ));
	$this -> tmpl -> setVar( "_login", $this -> q_param['login']);
	$this -> tmpl -> setVar( "_password", $this -> q_param['password']);

  	//Выход пользователя
  	if ( $this -> q_param["exit"] ) {

		setcookie("random_number", "", time() - 3600, "/", $this->getDomen() );
		setcookie("client_id", "", time() - 3600, "/", $this->getDomen() );

		$location = $this->isProtectedPage() ? $this->getAuthPath() : 'index.php';
		$location = $location ? $location : '/';

		header("Location: $location");
		// бессмысленно возвращать значение, т.к. браузер должен уйти на другой url
		// exit(0);
		return false;
  	}

   	if ( ( !$this -> q_param["login"] || !$this -> q_param["password"] ) && !$this->isRegistratedClient()) {
   	    // нет запроса на авторизацию или еще не авторизован
        return false;
    }

    $use_cookies = !isset($this->q_param["login"]) && !isset($this->q_param["password"]) && $this->isRegistratedClient();

  	$sSQL_client = "select * from CLIENT where " .
  			( $use_cookies ?
                "CLIENT_ID = '" . $_COOKIE['client_id'] . "' and RANDOM_NUMBER = '" . $_COOKIE['random_number'] . "'" :
                "EMAIL = '" . htmlspecialchars($this->q_param["login"], ENT_QUOTES ) . "' and PASSWORD = '" . htmlspecialchars($this->q_param['password'],ENT_QUOTES) . "'" );

  	$client_arr = sql_select($sSQL_client);

	$this -> tmpl -> setVar( "_name", $client_arr[0]['NAME']);
	$this -> tmpl -> setVar( "_surname", $client_arr[0]['SURNAME']);

  	//Если пользователь уже прошел аутентификацию
  	if ( $this -> isRegistratedClient() ) {

  		$this -> tmpl -> setVar( "_is_registrated", 1);

		if ($this -> q_param['from_url']) {
            header("Location: ".base64_decode($this -> q_param['from_url']));
    		// желательно прекратить сценарий после отправки такого заголовка
    		// exit(0);
        }
  		return true;
  	}

  	if (count($client_arr) == 0) {
		$this -> tmpl -> setVar( "_is_error", 1);
  		return false;
  	}

	$this -> setCookieToClient($client_arr[0]['CLIENT_ID'], $client_arr[0]['RANDOM_NUMBER']);

	$this -> tmpl -> setVar( "_is_registrated", 1);

    if ($this->q_param['from_url']) {
	    $location = base64_decode($this->q_param['from_url']);
	}
	elseif($this->q_param['login'] && $this->q_param['password']) {
	    $location = $this->go_to_page($this->view_param['goToData']);
	} else {
	    $location = 'index.php';
	}

	header("Location: $location");
	// бессмысленно возвращать значение, т.к. браузер должен уйти на другой url
	// exit(0);
	return $client_arr;
  }

  /**
   * Проверяет, состоит ли переданная строка только из цифр,
   * кол-во которых должно находится в пределах от $minlength до $maxlength
   *
   * @since 20061219
   * @param string $number_str Строка для проверки
   * @param int $minlength Минимальная длина строки из цифр
   * @param int $maxlength Максимальная длина цифровой строки
   * @param bool $unsigned Позволяет оценивать знаковые/беззнаковые значения
   * @return bool
   */
  function ValidIntStr($number_str, $minlength = 10, $maxlength = 18, $unsigned = true) {
      $sign_str = !$unsigned ? "(?:\+|-)?\s?" : '';
      return (1 === preg_match("/^{$sign_str}[\d]{{$minlength},{$maxlength}}$/", $number_str));
  }

  /**
   * Проверяет на допустимость значения в клиентских cookies
   *
   * @since 20061219
   * @return bool
   */
  function ValidClientCookies() {

	if (!isset($_COOKIE['random_number']) || !isset($_COOKIE['client_id'])) {
        return false;
    } elseif (!$this->ValidIntStr($_COOKIE['random_number'], 10, 18, true) || intval($_COOKIE['client_id']) <= 0) {
        return false;
    }

    return true;

  }

  /**
   * Проверяет регистрацию пользователя.
   *
   * @return boolean
   */
  function isRegistratedClient() {

	if (!$this->ValidClientCookies()) {
        return false;
    }

	return (count(sql_select("select * from CLIENT"
                            . " where CLIENT_ID = {$_COOKIE['client_id']}"
                            . " and RANDOM_NUMBER = {$_COOKIE['random_number']}")) > 0);
  }

  /**Возвращает запись текущего пользователя. Если пользователь авторизован - возвращает его запись, если нет - возвращает false
   * Применяется в форуме (вариант интеграции с модулем CLIENT)
   * @return mixed
   */
  function getCurrentClient() {

	if (!$this->ValidClientCookies()) {
        return false;
    }

    $client = sql_select("select * from CLIENT"
                        . " where CLIENT_ID = {$_COOKIE['client_id']}"
                        . " and RANDOM_NUMBER = {$_COOKIE['random_number']}");

	return (count($client) > 0 ? $client[0] : false);
  }

  /**Возвращает запись произвольного пользователя. Если пользователь существует - возвращает его запись, если нет - возвращает false
   * Применяется в форуме (вариант интеграции с модулем CLIENT)
   * @return mixed
   */
	function getClientById($client_id) {
		$client=sql_select("select * from CLIENT where CLIENT_ID = ".intval($client_id));
		if(count($client)>0){
			return $client[0];
		}else{
			return false;
		}
	}

  /**Устанавливает 'куки' на стороне аутентифицированного пользователя
   * @return void
   */
  function setCookieToClient($clientID, $randomNumber) {

	if (!$this -> q_param['outComputer']) $time = time() + 365*24*60*60;

	setcookie('client_id', 		$clientID, 		$time, '/', $this->getDomen() );
	setcookie('random_number', 	$randomNumber, 	$time, '/', $this->getDomen() );
  }


  /**Возвращает URL сайта, для установки кук
   * @return mixed
   */
  function getDomen(){
    $site = sql_select("select HOST from SITE order by SITE_ID");
    return ( count($site)>0 ) ? ".".$site[0]["HOST"] : "";
  }


  /**Возвращает url товара.
   * @return mixed
   */
  function getProductUrl ($content_id) {

	// Выбирается для данной страницы
	$page_row = sql_select("select distinct
							      TA.TEMPLATE_AREA_ID as TAREA_ID,
							      P.PARENT_ID as PARENT_ID,
							      P.DIR_NAME as DIR_NAME
							from
							    CONTENT_MAP CM,
							    PRODUCT PR,
							    INF_BLOCK IB,
							    PRG_MODULE PM,
							    PAGE_AREA PA,
							    TEMPLATE_AREA TA,
							    PAGE P
							where
							     CM.CONTENT_ID = ".intval($content_id)." and
							     CM.INF_BLOCK_ID = IB.INF_BLOCK_ID and
							     PR.CONTENT_ID = CM.CONTENT_ID and
							     PR.VERSION = ".intval($this -> version)." and
							     PR.LANG_ID = ".intval($this -> lang_id)." and
							     PM.CLASS_NAME = 'dynamic_catalogue' and
							     PM.PRG_MODULE_ID = IB.PRG_MODULE_ID and
							     IB.INF_BLOCK_ID = ".intval($this -> block_id)." and
							     IB.INF_BLOCK_ID = PA.INF_BLOCK_ID and
							     PA.TEMPLATE_AREA_ID = TA.TEMPLATE_AREA_ID and
							     TA.IS_MAIN  = 1 and
							     PA.PAGE_ID = P.PAGE_ID and
							     PA.VERSION = P.VERSION and
							     P.PAGE_ID = ".intval($this -> page_id)." and
							     P.SITE_ID = ".intval($this -> site_id)." and
							     P.VERSION = ".intval($this -> version)." and
							     P.LANG_ID = ".intval($this -> lang_id)."
							limit 0,1");

	// Ищется вообще любой блок, который размещен в главной области и в котором есть искомый элемент контента (товар)
	if (!$page_row) {

		$page_row = sql_select("select distinct
								      TA.TEMPLATE_AREA_ID as TAREA_ID,
								      P.PARENT_ID as PARENT_ID,
								      P.DIR_NAME as DIR_NAME
								from
								    CONTENT_MAP CM,
								    PRODUCT PR,
								    INF_BLOCK IB,
								    PRG_MODULE PM,
								    PAGE_AREA PA,
								    TEMPLATE_AREA TA,
								    PAGE P
								where
								     CM.CONTENT_ID = ".intval($content_id)." and
								     CM.INF_BLOCK_ID = IB.INF_BLOCK_ID and
								     PR.CONTENT_ID = CM.CONTENT_ID and
								     PR.VERSION = ".intval($this -> version)." and
								     PR.LANG_ID = ".intval($this -> lang_id)." and
								     PM.CLASS_NAME = 'dynamic_catalogue' and
								     PM.PRG_MODULE_ID = IB.PRG_MODULE_ID and
								     IB.INF_BLOCK_ID = PA.INF_BLOCK_ID and
								     PA.TEMPLATE_AREA_ID = TA.TEMPLATE_AREA_ID and
								     TA.IS_MAIN  = 1 and
								     PA.PAGE_ID = P.PAGE_ID and
								     PA.VERSION = P.VERSION and
								     P.SITE_ID = ".intval($this -> site_id)." and
								     P.VERSION = ".intval($this -> version)." and
								     P.LANG_ID = ".intval($this -> lang_id)."
								limit 0,1");
	}

	//Если товар удален из БД
	if ( !count($page_row) ) return false;

	$parent = $page_row[0]["PARENT_ID"];
	$path = $page_row[0]["DIR_NAME"]."/";
	while ( $parent != 0 ) {
		$parent_rows = sql_select("SELECT PARENT_ID, DIR_NAME FROM PAGE WHERE PAGE_ID = ".intval($parent)." and PAGE.VERSION = ".intval($this -> version));
		$path = $parent_rows[0]["DIR_NAME"] . "/" . $path;
	    $parent = $parent_rows[0]["PARENT_ID"];
	}
	$path = "/" . $path;

	return $path . "index.php?id" . $page_row[0]["TAREA_ID"] . "=" . $content_id;
  }

  /**Возвращает ссылку на страницу модуля. Выбирает первую сверху.
   * @return mixed
   */
  function getUrlForModule($moduleName) {

	if ($page_id = sql_select("select
							      PA.PAGE_ID as PAGE_ID,
							      PA.TEMPLATE_AREA_ID as TAREA_ID
							from
							    PRG_MODULE PM,
							    INF_BLOCK IB,
							    PAGE_AREA PA,
							    PAGE P,
							    TEMPLATE_AREA TA
							where
							     PM.CLASS_NAME = '".db_quote($moduleName)."' and
							     PM.PRG_MODULE_ID = IB.PRG_MODULE_ID and
							     IB.INF_BLOCK_ID = PA.INF_BLOCK_ID and
							     P.SITE_ID = ".intval($this -> site_id)." and
							     P.VERSION = ".intval($this -> version)." and
							     P.LANG_ID = ".intval($this -> lang_id)." and
							     P.PAGE_ID = PA.PAGE_ID and
							     P.VERSION = PA.VERSION and
							     PA.TEMPLATE_AREA_ID = TA.TEMPLATE_AREA_ID
							order by
							      TA.IS_MAIN desc"))
		return $this -> go_to_page($page_id[0]['PAGE_ID']);
	else return false;
  }

  /**Получает tarea_id информационного блока в котором размещен модуль на данной странице.
   * При условии что "Динамический каталог" и "Корзина" находяться на одной странице
   * @return mixed
   */
  function getModuleTAreaID($moduleClassName) {

	if ($tarea = sql_select("select
						      PA.TEMPLATE_AREA_ID as TAREA_ID
						from
						    PRG_MODULE PM,
						    INF_BLOCK IB,
						    PAGE_AREA PA
						where
						     PM.CLASS_NAME = '".db_quote($moduleClassName)."' and
						     PM.PRG_MODULE_ID = IB.PRG_MODULE_ID and
						     IB.INF_BLOCK_ID = PA.INF_BLOCK_ID and
						     PA.PAGE_ID = ".intval($this -> page_id)." and
						     PA.VERSION = ".intval($this -> version)))
		return $tarea[0]['TAREA_ID'];
	else return false;
  }

  /**Возвращает строку с набором (inf_block_id) инф. блоков модуля, которые размещены в разделах front-end'a в главной области.
   * @return string
   */
  function getBlockSetForModule($moduleClassName) {//имя класса модуля

	$moduleID = sql_select("select PRG.PRG_MODULE_ID as MODULE_ID from PRG_MODULE PRG where CLASS_NAME='{$moduleClassName}'");
	// Выбор всех инф. блоков использующих данный модуль
	$infBlockArr = sql_select("select distinct
								      IB.INF_BLOCK_ID
								from
								    INF_BLOCK IB,
								    PAGE_AREA PA,
								    PAGE P,
								    SITE S,
								    TEMPLATE_AREA TA
								where
								     IB.PRG_MODULE_ID = ".intval($moduleID[0]['MODULE_ID'])." and
								     IB.INF_BLOCK_ID = PA.INF_BLOCK_ID and
								     PA.VERSION = ".intval($this -> version)." and
								     PA.TEMPLATE_AREA_ID = TA.TEMPLATE_AREA_ID and
								     TA.IS_MAIN = 1 and
								     PA.PAGE_ID = P.PAGE_ID and
								     P.SITE_ID = ".intval($this -> site_id));
	return $this -> getSet($infBlockArr, 'INF_BLOCK_ID');
  }

  /**Возвращает преобразованную строку (текст) для письма
   * @return string
   */
  function getMailStr($str, $base = '') {

	$str = convert_cyr_string($str, 'UTF-8', 'KOI8-R');
	#$str = convert_cyr_string($str, 'WINDOWS-1251', 'KOI8-R');
	if ( $base != 'noBase64' ) $str = base64_encode($str);
	return $str;
  }

  /**Отсылает письмо
   * @return void
   */
  function sendMail($param) {
	global $os_type;
	$mail = new vlibMimeMail;
	if (isset($os_type) && $os_type == "windows") {
		$mail -> to($param['to']);
		$mail -> from($param['from']);
		$mail -> subject($param['subject']);
		$mail -> htmlBody($param['htmlBody'], 'windows-1251');
	} else {
		#$mail -> to($param['to'], "=?KOI8-R?B?".$this -> getMailStr($param['toName'])."?=");
		#$mail -> from($param['from'], "=?KOI8-R?B?".$this -> getMailStr($param['fromName'])."?=");
		#$mail -> subject("=?KOI8-R?B?".$this -> getMailStr($param['subject'])."?=");
		#$mail -> htmlBody($this -> getMailStr($param['htmlBody'], 'noBase64'), 'koi8-r');
		$mail -> to($param['to'], "=?UTF-8?B?".$this -> getMailStr($param['toName'])."?=");
		$mail -> from($param['from'], "=?UTF-8?B?".$this -> getMailStr($param['fromName'])."?=");
		$mail -> subject("=?UTF-8?B?".$this -> getMailStr($param['subject'])."?=");
		$mail -> htmlBody($this -> getMailStr($param['htmlBody'], 'noBase64'), 'utf-8');
	}
	$mail -> send();
  }

  /**Возвращает цену товара в опубликованной валюте и форматирует вывод
   * @return float
   */
  function getPrice($price, $currencyType = '') {

	if ($currencyType == 'main' && $this -> mainCurrency['VALUE']) $price = $this -> mainCurrency['VALUE']*$price;
	elseif ($this -> publishedCurrency['VALUE']) $price = $this -> publishedCurrency['VALUE']*$price;

	return sprintf("%.2f", $price);
  }

  /**Возвращает валюту, в которой выводятся цены товаров.
   * @return array
   */
  function getPublishedCurrency() {

	$currencyArr = sql_select("select * from CURRENCY_SHOP where IS_PUBLISHED = 1");
	return $currencyArr[0];
  }

  /**Возвращает валюту, по которой товар продается
   * @return array
   */
  function getMainCurrency() {

	$currencyArr = sql_select("select * from CURRENCY_SHOP where IS_MAIN = 1");
	return $currencyArr[0];
  }

  /**Возвращает множество элементов хэш-массива в виде строки.
   * @return string
   */
  function getSet($arr, $key) {

	foreach ($arr as $item)
		$set[] = intval($item[$key]);

	return implode(', ', $set);
  }

    /**
     * Проверяет закрыт ли раздел
     *
     * @return boolean
     */
    function isProtectedPage() {

        $query = "select
            P.IS_PROTECTED
        from
            PAGE P
        where
            P.PAGE_ID = '{$this->page_id}'
            and P.SITE_ID = '{$this->site_id}'
            and P.VERSION = '{$this->version}'";

        $result = sql_select($query);

        return $result[0][0] ? true : false;
    }

    /**
     * Возвращает путь к разделу, в главной области которого расположена форма аутентификации
     *
     * @return mixed
     */
    function getAuthPath() {

        $query = "SELECT
            MP.MODULE_PARAM_ID,
            PV.PARAM_VALUE_ID
        FROM
        	MODULE_PARAM MP,
        	PRG_MODULE PM,
        	PARAM_VALUE PV
        WHERE
        	MP.SYSTEM_NAME = 'view_mode' AND
        	PV.VALUE = 'auth' AND
        	PV.MODULE_PARAM_ID = MP.MODULE_PARAM_ID AND
            MP.PRG_MODULE_ID = PM.PRG_MODULE_ID AND
            CLASS_NAME = 'client'";

        $result = sql_select($query);
        $result = $result[0];

        $query = "SELECT
    		PA.PAGE_ID as PAGE_ID
    	FROM
    		PAGE_AREA PA,
    		PAGE P,
    		TEMPLATE_AREA TA,
    		PAGE_AREA_PARAM PAP
    	WHERE
    		P.SITE_ID = {$this->site_id} and
    		P.VERSION = {$this->version} and
    		P.LANG_ID = {$this->lang_id} and
            P.IS_PROTECTED = '0' and
    		P.PAGE_ID = PA.PAGE_ID and
    		P.VERSION = PA.VERSION and
    		PA.TEMPLATE_AREA_ID = TA.TEMPLATE_AREA_ID and
    		TA.IS_MAIN = '1' AND
    		PAP.PAGE_ID=PA.PAGE_ID AND
    		PAP.VERSION=PA.VERSION AND
    		PAP.TEMPLATE_AREA_ID=PA.TEMPLATE_AREA_ID AND
    		PAP.MODULE_PARAM_ID='{$result['MODULE_PARAM_ID']}' AND
    		PAP.VALUE='{$result['PARAM_VALUE_ID']}'
        LIMIT 0, 1";

        $result = sql_select($query);

        if ($result) {
            $path = $this->go_to_page($result[0][0]);
        } else {
            return false;
        }

        return ('index.php' == $path) ? false : $path;
    }
}

/**Вспомогательная функция для вывода содержимого массива с форматированием.
*/
function debugArr($arr) {

	echo '<pre>';
	print_r($arr);
	echo '</pre>';
}

/**
 * Фуникция для преобразования строкового поля в поле с плавающей точкой в SQL запросе.
 *
 * @param string $field
 * @return string
 */
function varcharToFloat($field) {

    global $db_type;

    $sql = array(
        'mssql' => "CAST($field as FLOAT)",
        'mysql' => "$field + 0.00"
    );

    return $sql[$db_type];
}

/**
 * Функция для определения полей в таблице, по которым может быть выполнен select distinct.
 *
 * @param string $table
 * @param string $alias
 * @return string
 */
function getDistinctFields($table, $alias = '') {

    global $db_type;

    if ($db_type == 'mysql') {
        return ($alias) ? "$alias.*" : '*';
    }

    if ($db_type == 'mssql') {

        $query = "select
	       COLUMN_NAME
        from
	       INFORMATION_SCHEMA.COLUMNS
        where
	       TABLE_NAME = '$table'
	       and DATA_TYPE not in ('text', 'ntext', 'image')";

        $fields = sql_select($query);

        foreach ($fields as $field) {
            $result[] = ($alias) ? "$alias.{$field['COLUMN_NAME']}" : $field['COLUMN_NAME'];
        }

        return implode(', ', $result);
    }
}

?>